﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YJKArchMethodLibrary.Utils;
using YJKStatisticTable.AreaTable.DataManager;

namespace YJKStatisticTable.AreaTable.StatisticControler
{
	public class StatisticalCalculater
	{
		public StatisticalCalculater(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
		}

		public void Calculate(List<StatisticalCalculater.AreaViewsInfoByFloor> areaInfoList, ref StatisticalResultData resultData)
		{
			List<StatisticalCalculater.SuiteInfoByFloor> list = new List<StatisticalCalculater.SuiteInfoByFloor>();
			this.CalculateSuiteInfo(areaInfoList, ref list);
			ArchAreaStatisticalData aasdata = null;
			this.CalculateArchAreaStatisticalData(list, ref aasdata);
			List<EstateSuiteAreaStatisticalData> esasdata = new List<EstateSuiteAreaStatisticalData>();
			this.CalculateEstateSuiteAreaStatisticalData(list, ref esasdata);
			List<HouseSuiteAreaStatisticalData> hsasdata = new List<HouseSuiteAreaStatisticalData>();
			this.CalculateHouseSuiteAreaStatisticalData(list, ref hsasdata);
			List<HouseSuiteAreaAnalyzeData> hsaadata = new List<HouseSuiteAreaAnalyzeData>();
			this.CalculateHouseSuiteAreaAnalyzeData(list, ref hsaadata);
			List<string> list2 = new List<string>();
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in list)
			{
				list2.Add(suiteInfoByFloor.m_Level.Name);
			}
			resultData = new StatisticalResultData(list2, aasdata, esasdata, hsasdata, hsaadata);
		}

		public void CalculateSuiteInfo(List<StatisticalCalculater.AreaViewsInfoByFloor> areaInfoList, ref List<StatisticalCalculater.SuiteInfoByFloor> calculateInfo)
		{
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			foreach (StatisticalCalculater.AreaViewsInfoByFloor areaViewsInfoByFloor in areaInfoList)
			{
				List<Area> allAreaByView = this.GetAllAreaByView(areaViewsInfoByFloor.m_FillAreaView.Id, document);
				List<ElementId> list = new List<ElementId>();
				double num = 0.0;
				foreach (Area area in allAreaByView)
				{
					AreaType areaType = AreaType.AT_None;
					if (AreaInfoManager.HaxExtensibleStorageInArea(area, ref areaType))
					{
						string text = "";
						string text2 = "";
						List<ElementId> collection = new List<ElementId>();
						AreaInfoManager.ReadExtensibleStorageFromArea(area, ref areaType, ref text, ref text2, ref collection);
						list.AddRange(collection);
						double num2 = area.get_Parameter(BuiltInParameter.ROOM_AREA).AsDouble();
						num += num2;
					}
				}
				List<ElementId> roomIdList = this.Unique(list);
				double num3 = 0.0;
				double num4 = 0.0;
				double num5 = 0.0;
				this.GetCalculateAreaInfo(false, document, roomIdList, ref num3, ref num4, ref num5);
				double num6 = 0.0;
				double num7 = 0.0;
				double num8 = 0.0;
				List<SuiteInfos> list2 = new List<SuiteInfos>();
				List<Area> allAreaByView2 = this.GetAllAreaByView(areaViewsInfoByFloor.m_SuiteAreaView.Id, document);
				foreach (Area area2 in allAreaByView2)
				{
					AreaType areaType2 = AreaType.AT_None;
					if (AreaInfoManager.HaxExtensibleStorageInArea(area2, ref areaType2))
					{
						string suiteNumbName = "";
						string hoomNumbName = "";
						List<ElementId> roomIdList2 = new List<ElementId>();
						AreaInfoManager.ReadExtensibleStorageFromArea(area2, ref areaType2, ref suiteNumbName, ref hoomNumbName, ref roomIdList2);
						double num9 = area2.get_Parameter(BuiltInParameter.ROOM_AREA).AsDouble();
						num8 += num9;
						double num10 = 0.0;
						double num11 = 0.0;
						double num12 = 0.0;
						this.GetCalculateAreaInfo(true, document, roomIdList2, ref num10, ref num11, ref num12);
						double num13 = num9 - num11 + num10;
						num6 += num12;
						string suiteName = this.GetSuiteName(document, roomIdList2);
						double num14 = num13 - num12 - num10;
						num7 += num14;
						double suitePublicArea = 0.0;
						double averagePublicArea = 0.0;
						SuiteInfos item = new SuiteInfos(hoomNumbName, suiteNumbName, suiteName, num12, num13, num10, num14, suitePublicArea, averagePublicArea, 1);
						list2.Add(item);
					}
				}
				double num15 = num - num8;
				double num16 = num - num6;
				double num17 = 0.0;
				foreach (SuiteInfos suiteInfos in list2)
				{
					num17 += suiteInfos.UseArea;
				}
				for (int i = 0; i < list2.Count; i++)
				{
					SuiteInfos suiteInfos2 = list2[i];
					double num18 = suiteInfos2.UseArea / num17;
					double suitePublicArea2 = num15 * num18;
					list2[i].SuitePublicArea = suitePublicArea2;
					double averagePublicArea2 = num16 * num18;
					list2[i].AveragePublicArea = averagePublicArea2;
				}
				Level level = areaViewsInfoByFloor.m_Level;
				StatisticalCalculater.SuiteInfoByFloor item2 = new StatisticalCalculater.SuiteInfoByFloor(level, list2);
				calculateInfo.Add(item2);
			}
		}

		private string GetSuiteName(Document doc, List<ElementId> roomIdList)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (ElementId elementId in roomIdList)
			{
				Element element = doc.GetElement(elementId);
				Room room = element as Room;
				if (room != null)
				{
					room.get_Parameter(BuiltInParameter.ROOM_NAME).AsString();
					if (RoomInfoManager.HaxExtensibleStorageInRoom(room))
					{
						double num4 = 0.0;
						RoomType roomType = RoomType.RT_Other;
						bool flag = false;
						RoomInfoManager.ReadExtensibleStorageFromRoom(room, ref num4, ref roomType, ref flag);
						if (roomType == RoomType.RT_Hall)
						{
							num++;
						}
						else if (roomType == RoomType.RT_Room)
						{
							num2++;
						}
						else if (roomType == RoomType.RT_Cell)
						{
							num3++;
						}
					}
				}
			}
			return string.Concat(new string[]
			{
				num2.ToString(),
				"室",
				num.ToString(),
				"厅",
				num3.ToString(),
				"卫"
			});
		}

		private void GetCalculateAreaInfo(bool isSuite, Document doc, List<ElementId> roomIdList, ref double balconyAreaValue, ref double realBalconyAreaValue, ref double useAreaValue)
		{
			foreach (ElementId elementId in roomIdList)
			{
				Element element = doc.GetElement(elementId);
				Room room = element as Room;
				if (room != null)
				{
					double num = 1.0;
					double num2 = room.get_Parameter(BuiltInParameter.ROOM_AREA).AsDouble();
					RoomType roomType = RoomType.RT_Other;
					bool flag = false;
					if (!RoomInfoManager.HaxExtensibleStorageInRoom(room))
					{
						if (!isSuite)
						{
							useAreaValue += num * num2;
						}
					}
					else
					{
						RoomInfoManager.ReadExtensibleStorageFromRoom(room, ref num, ref roomType, ref flag);
						if (flag)
						{
							balconyAreaValue += num * num2;
							realBalconyAreaValue += num2;
						}
						else
						{
							useAreaValue += num * num2;
						}
					}
				}
			}
		}

		private List<Area> GetAllAreaByView(ElementId viewId, Document doc)
		{
			List<Area> list = new List<Area>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, viewId).OfCategory(BuiltInCategory.OST_Areas);
			foreach (Element element in filteredElementCollector)
			{
				Area area = element as Area;
				if (area != null)
				{
					list.Add(area);
				}
			}
			return list;
		}

		private List<ElementId> Unique(List<ElementId> roomIdList)
		{
			List<ElementId> list = new List<ElementId>();
			IEnumerable<ElementId> enumerable = (from li in roomIdList
			select li).Distinct<ElementId>();
			foreach (ElementId item in enumerable)
			{
				list.Add(item);
			}
			return list;
		}

		private void CalculateArchAreaStatisticalData(List<StatisticalCalculater.SuiteInfoByFloor> calculateInfoList, ref ArchAreaStatisticalData resData)
		{
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			double num4 = 0.0;
			double num5 = 0.0;
			double num6 = 0.0;
			List<ArchAreaStatisticalFloorData> list = new List<ArchAreaStatisticalFloorData>();
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in calculateInfoList)
			{
				double num7 = 0.0;
				double num8 = 0.0;
				double num9 = 0.0;
				double num10 = 0.0;
				double num11 = 0.0;
				double num12 = 0.0;
				List<ArchAreaStatisticalRowData> list2 = new List<ArchAreaStatisticalRowData>();
				foreach (SuiteInfos suiteInfos in suiteInfoByFloor.m_SuiteInfosList)
				{
					double num13 = this.SquareFoot2SquareMeter(suiteInfos.UseArea);
					double num14 = this.SquareFoot2SquareMeter(suiteInfos.WallArea);
					double num15 = this.SquareFoot2SquareMeter(suiteInfos.BalconyArea);
					double num16 = this.SquareFoot2SquareMeter(suiteInfos.ArchArea);
					double num17 = this.SquareFoot2SquareMeter(suiteInfos.SuitePublicArea);
					double num18 = num16 + num17;
					ArchAreaStatisticalRowData item = new ArchAreaStatisticalRowData(suiteInfos.HoomNumbName, suiteInfos.SuiteNumbName, suiteInfos.SuiteName, num13, num14, num15, num16, num17, num18);
					list2.Add(item);
					num7 += num13;
					num8 += num14;
					num9 += num15;
					num10 += num16;
					num11 += num17;
					num12 += num18;
				}
				list2.Sort(new ArchAreaStatisticalRowDataComparer());
				string name = suiteInfoByFloor.m_Level.Name;
				ArchAreaStatisticalRowData floorFooting = new ArchAreaStatisticalRowData("合计", "--", "--", num7, num8, num9, num10, num11, num12);
				ArchAreaStatisticalFloorData item2 = new ArchAreaStatisticalFloorData(name, list2, floorFooting);
				list.Add(item2);
				num += num7;
				num2 += num8;
				num3 += num9;
				num4 += num10;
				num5 += num11;
				num6 += num12;
			}
			ArchAreaStatisticalRowData footing = new ArchAreaStatisticalRowData("合计", "--", "--", num, num2, num3, num4, num5, num6);
			resData = new ArchAreaStatisticalData(list, footing);
		}

		private List<SuiteCountInfoByFloor> CreateSuiteCountInfoListByFloor(List<StatisticalCalculater.SuiteInfoByFloor> calculateInfoList)
		{
			List<SuiteCountInfoByFloor> list = new List<SuiteCountInfoByFloor>();
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in calculateInfoList)
			{
				SuiteCountInfoByFloor item = new SuiteCountInfoByFloor(suiteInfoByFloor.m_Level.Name, 0);
				list.Add(item);
			}
			return list;
		}

		private void AddSuiteCountInfoToList(ref List<SuiteCountInfoByFloor> suiteCountInfoListByFloor, string floorName)
		{
			int num = suiteCountInfoListByFloor.FindIndex((SuiteCountInfoByFloor value) => value.m_FloorName.CompareTo(floorName) == 0);
			if (num == -1)
			{
				return;
			}
			suiteCountInfoListByFloor[num].m_Count++;
		}

		private void CalculateEstateSuiteAreaStatisticalData(List<StatisticalCalculater.SuiteInfoByFloor> calculateInfoList, ref List<EstateSuiteAreaStatisticalData> resData)
		{
			List<SuiteInfos> list = new List<SuiteInfos>();
			int num = 0;
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in calculateInfoList)
			{
				using (List<SuiteInfos>.Enumerator enumerator2 = suiteInfoByFloor.m_SuiteInfosList.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						SuiteInfos suiteInfos = enumerator2.Current;
						int num2 = list.FindIndex((SuiteInfos value) => value.IsSame(suiteInfos));
						if (num2 == -1)
						{
							list.Add(suiteInfos);
							double suiteUseArea = this.SquareFoot2SquareMeter(suiteInfos.UseArea);
							double wallArea = this.SquareFoot2SquareMeter(suiteInfos.WallArea);
							double balconyArea = this.SquareFoot2SquareMeter(suiteInfos.BalconyArea);
							double num3 = this.SquareFoot2SquareMeter(suiteInfos.ArchArea);
							double num4 = this.SquareFoot2SquareMeter(suiteInfos.SuitePublicArea);
							double archArea = num3 + num4;
							List<SuiteCountInfoByFloor> suiteCountInfoListByFloor = this.CreateSuiteCountInfoListByFloor(calculateInfoList);
							this.AddSuiteCountInfoToList(ref suiteCountInfoListByFloor, suiteInfoByFloor.m_Level.Name);
							EstateSuiteAreaStatisticalData item = new EstateSuiteAreaStatisticalData(suiteInfos.SuiteNumbName, suiteInfos.SuiteName, suiteUseArea, wallArea, balconyArea, num3, num4, archArea, suiteCountInfoListByFloor, 1);
							resData.Add(item);
						}
						else
						{
							this.AddSuiteCountInfoToList(ref resData[num2].m_SuiteCountInfoListByFloor, suiteInfoByFloor.m_Level.Name);
							resData[num2].m_Footing++;
						}
					}
				}
				num++;
			}
			resData.Sort(new EstateSuiteAreaStatisticalDataComparer());
		}

		private void CalculateHouseSuiteAreaStatisticalData(List<StatisticalCalculater.SuiteInfoByFloor> calculateInfoList, ref List<HouseSuiteAreaStatisticalData> resData)
		{
			List<SuiteInfos> list = new List<SuiteInfos>();
			int num = 0;
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in calculateInfoList)
			{
				using (List<SuiteInfos>.Enumerator enumerator2 = suiteInfoByFloor.m_SuiteInfosList.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						SuiteInfos suiteInfos = enumerator2.Current;
						int num2 = list.FindIndex((SuiteInfos value) => value.IsSame(suiteInfos));
						if (num2 == -1)
						{
							list.Add(suiteInfos);
							double num3 = this.SquareFoot2SquareMeter(suiteInfos.UseArea);
							double balconyArea = this.SquareFoot2SquareMeter(suiteInfos.BalconyArea);
							double num4 = this.SquareFoot2SquareMeter(suiteInfos.AveragePublicArea);
							double suiteArchArea = num3 + num4;
							List<SuiteCountInfoByFloor> suiteCountInfoListByFloor = this.CreateSuiteCountInfoListByFloor(calculateInfoList);
							this.AddSuiteCountInfoToList(ref suiteCountInfoListByFloor, suiteInfoByFloor.m_Level.Name);
							HouseSuiteAreaStatisticalData item = new HouseSuiteAreaStatisticalData(suiteInfos.SuiteNumbName, suiteInfos.SuiteName, num3, num4, suiteArchArea, balconyArea, suiteCountInfoListByFloor, 1);
							resData.Add(item);
						}
						else
						{
							this.AddSuiteCountInfoToList(ref resData[num2].m_SuiteCountInfoListByFloor, suiteInfoByFloor.m_Level.Name);
							resData[num2].m_Footing++;
						}
					}
				}
				num++;
			}
			resData.Sort(new HouseSuiteAreaStatisticalDataComparer());
		}

		private void CalculateHouseSuiteAreaAnalyzeData(List<StatisticalCalculater.SuiteInfoByFloor> calculateInfoList, ref List<HouseSuiteAreaAnalyzeData> resData)
		{
			List<SuiteInfos> list = new List<SuiteInfos>();
			int num = 0;
			foreach (StatisticalCalculater.SuiteInfoByFloor suiteInfoByFloor in calculateInfoList)
			{
				using (List<SuiteInfos>.Enumerator enumerator2 = suiteInfoByFloor.m_SuiteInfosList.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						SuiteInfos suiteInfos = enumerator2.Current;
						int num2 = list.FindIndex((SuiteInfos value) => value.IsSame(suiteInfos));
						if (num2 == -1)
						{
							list.Add(new SuiteInfos(suiteInfos)
							{
								SuiteCount = 1
							});
						}
						else
						{
							list[num2].SuiteCount++;
						}
					}
				}
				num++;
			}
			list.Sort(new SuiteInfosComparer());
			List<SuiteInfos> item = new List<SuiteInfos>();
			List<SuiteInfos> item2 = new List<SuiteInfos>();
			List<List<SuiteInfos>> list2 = new List<List<SuiteInfos>>();
			list2.Add(item);
			list2.Add(item2);
			List<string> list3 = new List<string>();
			list3.Add("90平米内");
			list3.Add("90平米外");
			foreach (SuiteInfos suiteInfos3 in list)
			{
				double val = this.SquareFoot2SquareMeter(suiteInfos3.ArchArea);
				if (Geometry.LessThan(val, 90.0))
				{
					list2[0].Add(suiteInfos3);
				}
				else
				{
					list2[1].Add(suiteInfos3);
				}
			}
			double num3 = 0.0;
			for (int i = 0; i < list2.Count; i++)
			{
				List<SuiteInfos> list4 = list2[i];
				List<string> list5 = new List<string>();
				List<List<SuiteInfos>> list6 = new List<List<SuiteInfos>>();
				using (List<SuiteInfos>.Enumerator enumerator2 = list4.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						SuiteInfos suiteInfos = enumerator2.Current;
						int num4 = list5.FindIndex((string value) => value.CompareTo(suiteInfos.SuiteName) == 0);
						if (num4 == -1)
						{
							list6.Add(new List<SuiteInfos>
							{
								suiteInfos
							});
							list5.Add(suiteInfos.SuiteName);
						}
						else
						{
							list6[num4].Add(suiteInfos);
						}
					}
				}
				double num5 = 0.0;
				double num6 = 0.0;
				double num7 = 0.0;
				double num8 = 0.0;
				double num9 = 0.0;
				double num10 = 0.0;
				double num11 = 0.0;
				double num12 = 0.0;
				int num13 = 0;
				List<HouseSuiteAreaAnalyzeListBySuite> list7 = new List<HouseSuiteAreaAnalyzeListBySuite>();
				foreach (List<SuiteInfos> list8 in list6)
				{
					if (list8.Count >= 1)
					{
						double num14 = 0.0;
						double num15 = 0.0;
						double num16 = 0.0;
						double num17 = 0.0;
						double num18 = 0.0;
						double num19 = 0.0;
						double num20 = 0.0;
						double num21 = 0.0;
						int num22 = 0;
						List<HouseSuiteAreaAnalyzeRowData> list9 = new List<HouseSuiteAreaAnalyzeRowData>();
						foreach (SuiteInfos suiteInfos2 in list8)
						{
							double num23 = this.SquareFoot2SquareMeter(suiteInfos2.UseArea);
							double num24 = this.SquareFoot2SquareMeter(suiteInfos2.WallArea);
							double num25 = this.SquareFoot2SquareMeter(suiteInfos2.BalconyArea);
							double num26 = this.SquareFoot2SquareMeter(suiteInfos2.AveragePublicArea);
							double num27 = num23 + num26;
							int suiteCount = suiteInfos2.SuiteCount;
							double num28 = num27 * (double)suiteCount;
							double num29 = 0.0;
							HouseSuiteAreaAnalyzeRowData item3 = new HouseSuiteAreaAnalyzeRowData(suiteInfos2.SuiteNumbName, num23, num26, num27, num25, (double)suiteInfos2.SuiteCount, num28, num29);
							list9.Add(item3);
							num14 += num23;
							num15 += num24;
							num16 += num25;
							num17 += num27;
							num18 += num26;
							num22 += suiteCount;
							num20 += num28;
							num21 += num29;
						}
						HouseSuiteAreaAnalyzeRowData footing = new HouseSuiteAreaAnalyzeRowData("合计", num14, num18, num17, num16, (double)num22, num20, num21);
						string suiteName = list8[0].SuiteName;
						HouseSuiteAreaAnalyzeListBySuite item4 = new HouseSuiteAreaAnalyzeListBySuite(suiteName, list9, footing);
						list7.Add(item4);
						num5 += num14;
						num6 += num15;
						num7 += num16;
						num8 += num17;
						num9 += num18;
						num10 += num19;
						num13 += num22;
						num11 += num20;
						num3 += num11;
						num12 += num21;
					}
				}
				HouseSuiteAreaAnalyzeRowData sumFooting = new HouseSuiteAreaAnalyzeRowData("合计", num5, num9, num8, num7, (double)num13, num11, num12);
				string statisticalRange = list3[i];
				HouseSuiteAreaAnalyzeData item5 = new HouseSuiteAreaAnalyzeData(statisticalRange, list7, sumFooting);
				resData.Add(item5);
			}
			for (int i = 0; i < resData.Count; i++)
			{
				HouseSuiteAreaAnalyzeData houseSuiteAreaAnalyzeData = resData[i];
				for (int j = 0; j < houseSuiteAreaAnalyzeData.m_Data.Count; j++)
				{
					HouseSuiteAreaAnalyzeListBySuite houseSuiteAreaAnalyzeListBySuite = houseSuiteAreaAnalyzeData.m_Data[j];
					for (int k = 0; k < houseSuiteAreaAnalyzeListBySuite.m_Data.Count; k++)
					{
						HouseSuiteAreaAnalyzeRowData houseSuiteAreaAnalyzeRowData = houseSuiteAreaAnalyzeListBySuite.m_Data[k];
						double num30 = Convert.ToDouble(houseSuiteAreaAnalyzeRowData.m_SumSuiteArchArea);
						houseSuiteAreaAnalyzeRowData.m_SumSuiteRate = (num30 / num3 * 100.0).ToString("f0") + "%";
					}
					double num31 = Convert.ToDouble(houseSuiteAreaAnalyzeListBySuite.m_Footing.m_SumSuiteArchArea);
					houseSuiteAreaAnalyzeListBySuite.m_Footing.m_SumSuiteRate = (num31 / num3 * 100.0).ToString("f0") + "%";
				}
				double num32 = Convert.ToDouble(houseSuiteAreaAnalyzeData.m_SumFooting.m_SumSuiteArchArea);
				houseSuiteAreaAnalyzeData.m_SumFooting.m_SumSuiteRate = (num32 / num3 * 100.0).ToString("f0") + "%";
			}
		}

		private double SquareFoot2SquareMeter(double value)
		{
			return value * Math.Pow(0.3048, 2.0);
		}

		private ExternalCommandData m_Revit;

		public struct AreaViewsInfoByFloor
		{
			public AreaViewsInfoByFloor(Level level, ViewPlan fillAreaView, ViewPlan suiteAreaView)
			{
				this.m_Level = level;
				this.m_FillAreaView = fillAreaView;
				this.m_SuiteAreaView = suiteAreaView;
			}

			public Level m_Level;

			public ViewPlan m_FillAreaView;

			public ViewPlan m_SuiteAreaView;
		}

		public struct SuiteInfoByFloor
		{
			public SuiteInfoByFloor(Level level, List<SuiteInfos> suiteInfosList)
			{
				this.m_Level = level;
				this.m_SuiteInfosList = suiteInfosList;
			}

			public Level m_Level;

			public List<SuiteInfos> m_SuiteInfosList;
		}
	}
}
